/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.designer.querybuilder;
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceAdapter;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.beans.PropertyVetoException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import ro.nextreports.designer.Globals;
import ro.nextreports.designer.querybuilder.datatransfer.InternalFrameTransferable;
import ro.nextreports.designer.ui.list.CheckListItem;
import ro.nextreports.designer.util.I18NSupport;
import ro.nextreports.designer.util.ImageUtil;
import ro.nextreports.engine.querybuilder.sql.Column;
import ro.nextreports.engine.querybuilder.sql.Table;
/**
* @author Decebal Suiu
*/
public class DBTableInternalFrame extends JInternalFrame {
private Table table;
private JScrollPane scroll;
private DefaultListModel model = new DefaultListModel();
private ColumnsListBox columnsListBox = new ColumnsListBox();
private DBTablesDesktopPane desktop;
// variable used for selection :
// for join drag and drop when start dragging in the source (gestureStarted=true) the selection will not be modified
boolean gestureStarted = false;
public DBTableInternalFrame(final DBTablesDesktopPane desktop, final Table table, Map<String, List<CheckListItem>> itemMap) {
super(table.getAlias() + " (" + table.getSchemaName() + "." + table.getName() + ")", true, true, false, false);
this.desktop = desktop;
this.table = table;
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
customizeTable();
String key = table.getAlias();
if (key == null) {
key = table.getName();
}
List<CheckListItem> items = itemMap.get(key);
for (CheckListItem i : items) {
model.addElement(i);
}
columnsListBox.setModel(model);
addComponents();
setFrameIcon(ImageUtil.TABLE_IMAGE_ICON);
addInternalFrameListener(new InternalFrameAdapter() {
public void internalFrameClosing(InternalFrameEvent e) {
Collection<JoinLine> joinLines = DBTableInternalFrame.this.desktop
.getJoinLinesForInternalFrame(DBTableInternalFrame.this);
boolean remove = false;
if (joinLines.size() > 0) {
String[] message = {
I18NSupport.getString("internal.frame.active.joins"),
I18NSupport.getString("internal.frame.delete.joins"),
I18NSupport.getString("internal.frame.close") };
int option = JOptionPane.showOptionDialog(Globals
.getMainFrame(), message, I18NSupport.getString("internal.frame.confirm.close"),
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (option == JOptionPane.YES_OPTION) {
remove = true;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
DBTableInternalFrame.this.desktop.removeJoinLines(joinLines);
}
} else {
remove = true;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
if (remove) {
// when closing a table
// must remove match criteria
// must remove group by columns
// must remove the selected columns of that table from model and from select query
DBTableInternalFrame.this.desktop.getQuerBuilderPanel().getSelectQuery().removeMatchCriterias(table.getAlias());
DBTableInternalFrame.this.desktop.getQuerBuilderPanel().getSelectQuery().removeOrMatchCriterias(table.getAlias(), 0);
DBTableInternalFrame.this.desktop.getQuerBuilderPanel().getSelectQuery().removeGroupByColumns(table.getAlias());
int size = model.getSize();
for (int i = 0; i < size; i++) {
CheckListItem item = (CheckListItem) model.getElementAt(i);
if (item.isSelected()) {
desktop.getQuerBuilderPanel().getDesignPanel().removeColumn((Column) item.getObject());
}
}
}
}
});
columnsListBox.setFrame(this);
((BasicInternalFrameUI) getUI()).getNorthPane().setToolTipText(table.getAlias() + " (" + table.getSchemaName() + "." + table.getName() + ")");
}
private void customizeTable() {
columnsListBox.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
columnsListBox.setSelectionModel(new DefaultListSelectionModel() {
public void setSelectionInterval(int index0, int index1) {
if (!gestureStarted) {
super.setSelectionInterval(index0, index1);
}
}
});
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(columnsListBox,
DnDConstants.ACTION_MOVE, new TableDragGestureListener());
columnsListBox.setDropTarget(new DropTarget(columnsListBox, DnDConstants.ACTION_MOVE,
new TableDropTargetListener()));
}
private void addComponents() {
scroll = new JScrollPane(columnsListBox);
getContentPane().add(scroll, BorderLayout.CENTER);
JScrollBar vScrollBar = scroll.getVerticalScrollBar();
vScrollBar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
desktop.repaint();
}
});
}
public Column getSelectedColumn() {
return (Column) ((CheckListItem) columnsListBox.getSelectedValue()).getObject();
}
public int getSelectedRow() {
return columnsListBox.getSelectedIndex();
}
public Table getTable() {
return table;
}
public void tableColumnRemoved(String columnName) {
for (int row = 0; row < model.getSize(); row++) {
CheckListItem item = (CheckListItem) model.getElementAt(row);
String value = item.getText();
if (value.equals(columnName)) {
try {
setSelected(true);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
item.setSelected(false);
model.setElementAt(item, row);
}
}
}
public void allTableColumnsRemoved() {
for (int row = 0; row < model.getSize(); row++) {
CheckListItem item = (CheckListItem) model.getElementAt(row);
boolean checked = item.isSelected();
if (checked) {
item.setSelected(false);
model.setElementAt(item, row);
}
}
}
public int getJoinY(int row) {
// y-ul pentru o linie, raportat la dimensiunea tabelei
int yForRow = getYForRow(row);
// y-ul partii vizibile a tabelei in viewport, raportat la y-ul tabelei
int viewRectY = scroll.getViewport().getViewRect().y;
// inaltimea titlebar-ului ferestrei interne
int titlebarHeight = ((BasicInternalFrameUI) getUI()).getNorthPane().getHeight();
// distanta dintre bordura ferestrei si continutul ei
int borderInsetsTop = getBorder().getBorderInsets(this).top;
// inaltimea partii vizibile a tabelei
int extentSizeHeight = scroll.getViewport().getExtentSize().height;
// daca linia din tabela nu e vizibila si e mai sus decat liniile din
// viewport, join-ul va porni de la baza titlebar-ului
int y = borderInsetsTop + titlebarHeight;
if ((viewRectY <= yForRow) && (yForRow <= (viewRectY + extentSizeHeight))) {
// linia e vizibila, adaug offset-ul pana la ea
y += (yForRow - viewRectY);
}
if (yForRow > (viewRectY + extentSizeHeight)) {
// linia nu e vizibila si e mai jos decat liniile din viewport,
// join-ul va porni de la baza ferestrei
y += extentSizeHeight;
}
return y;
}
private int getYForRow(int row) {
int rowHeight = columnsListBox.getFixedCellHeight();
int rowCount = columnsListBox.getVisibleRowCount();
int y = 0;
for (int i = 0; i < model.getSize(); i++) {
if (i == row) {
// am gasit linia pentru join, adaug jumatate din inaltimea ei
y += (rowHeight / 2);
break;
}
// nu am gasit inca linia pentru join, mai adaug inaltimea unei
// linii
y += rowHeight;
}
return y;
}
private class TableDragGestureListener implements DragGestureListener {
public void dragGestureRecognized(DragGestureEvent dge) {
Transferable transferable = new InternalFrameTransferable(DBTableInternalFrame.this);
dge.startDrag(DragSource.DefaultLinkNoDrop, transferable, new TableDragSourceListener());
}
}
private class TableDragSourceListener extends DragSourceAdapter {
public void dragEnter(DragSourceDragEvent dsde) {
// Point point = dsde.getLocation();
// if (columnsListBox.getBounds().contains(point)) {
// dsde.getDragSourceContext().setCursor(DragSource.DefaultLinkNoDrop);
// return;
// }
gestureStarted = true;
if ((dsde.getDropAction() & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
dsde.getDragSourceContext().setCursor(DragSource.DefaultLinkDrop);
}
}
public void dragExit(DragSourceEvent dse) {
dse.getDragSourceContext().setCursor(DragSource.DefaultLinkNoDrop);
}
public void dragDropEnd(DragSourceDropEvent dsde) {
gestureStarted = false;
if (dsde.getDropSuccess()) {
int row = columnsListBox.getSelectedIndex();
// System.out.println("row = " + row);
CheckListItem item = (CheckListItem) model.getElementAt(row);
// System.out.println("item = " + item.getText());
// item.setSelected(true);
model.setElementAt(item, row);
}
}
}
private class TableDropTargetListener extends DropTargetAdapter {
public void dragEnter(DropTargetDragEvent dtde) {
if (isDragOk(dtde)) {
selectRowAtPoint(dtde.getLocation());
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
} else {
dtde.rejectDrag();
}
}
public void dragOver(DropTargetDragEvent dtde) {
if (isDragOk(dtde)) {
selectRowAtPoint(dtde.getLocation());
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
} else {
dtde.rejectDrag();
}
}
public void drop(DropTargetDropEvent dtde) {
gestureStarted = false;
if ((dtde.getDropAction() & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
Transferable t = dtde.getTransferable();
try {
DBTableInternalFrame iFrame = (DBTableInternalFrame) t
.getTransferData(InternalFrameTransferable.DATA_FLAVOR);
if (iFrame != DBTableInternalFrame.this) {
JoinLine joinLine = new JoinLine(iFrame, iFrame
.getSelectedRow(), DBTableInternalFrame.this,
columnsListBox.getSelectedIndex());
desktop.addJoinLine(joinLine);
desktop.repaint();
}
} catch (Exception e) {
e.printStackTrace();
}
dtde.dropComplete(true);
}
}
private boolean isDragOk(DropTargetDragEvent dtde) {
if (dtde.getCurrentDataFlavors().length < 1) {
return false;
}
if (dtde.getCurrentDataFlavors()[0]
.equals(InternalFrameTransferable.DATA_FLAVOR)) {
return true;
}
return false;
}
private void selectRowAtPoint(Point point) {
int rowAtPoint = columnsListBox.locationToIndex(point);
columnsListBox.setSelectionInterval(rowAtPoint, rowAtPoint);
}
}
public DBTablesDesktopPane getDesktopPane() {
return desktop;
}
public void selectColumns(List<Column> columns) {
columnsListBox.selectColumns(columns);
}
public void selectColumn(Column column) {
columnsListBox.selectColumn(column);
}
public void selectRow(int index) {
columnsListBox.selectRow(index);
}
public int getIndex(Column column) {
return columnsListBox.getIndex(column);
}
public int getIndex(String tableName, String columnName) {
return columnsListBox.getIndex(tableName, columnName);
}
public Column getColumn(int index) {
return columnsListBox.getColumn(index);
}
}